package com.alkin.thing.common.utils;

import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.Workbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;

import javax.servlet.http.HttpServletResponse;
import java.beans.PropertyDescriptor;
import java.io.BufferedOutputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static java.util.stream.Collectors.toList;

public class ExportUtils {
    private static Logger logger = LoggerFactory.getLogger(ExportUtils.class);

    public static <T> List<String[]> convertExportData(List<T> list, String[] props) {
        List<Map<String, String>> maps = convertExportData(list);

        return maps.stream().map(m -> {
            String[] data = new String[props.length];
            for (int i = 0; i < props.length; i++) {
                data[i] = m.get(props[i]);
            }
            return data;
        }).collect(toList());

    }

    public static <T> List<Map<String, String>> convertExportData(List<T> list) {
        List<Map<String, String>> dataList = new ArrayList<>();
        if (list == null || list.isEmpty()) {
            return dataList;
        }
        try {
            PropertyDescriptor[] propertyDescriptors = BeanUtils.getPropertyDescriptors(list.get(0).getClass());

            Map<String, String> map = null;
            for (T vo : list) {
                map = new HashMap<>();
                for (PropertyDescriptor pd : propertyDescriptors) {
                    Object val = pd.getReadMethod().invoke(vo);
                    if (val == null) {
                        val = "";
                    } else if (val.toString().contains(",")) {
                        val = "\"" + val.toString() + "\"";
                    }
                    map.put(pd.getName(), val.toString());
                }
                dataList.add(map);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return dataList;
    }

    /**
     * 方法名：exportExcel
     * 功能：导出Excel
     * 描述：
     * 创建人：typ
     * 创建时间：2018/10/19 16:00
     * 修改人：
     * 修改描述：
     * 修改时间：
     */
    public static void exportExcel(HttpServletResponse response, String fileName, String[] head, List<String[]> data) {
        logger.info("导出开始，fileName:{}", fileName);
        try {
            //实例化HSSFWorkbook
            HSSFWorkbook workbook = new HSSFWorkbook();
            //创建一个Excel表单，参数为sheet的名字
            HSSFSheet sheet = workbook.createSheet("sheet");
            //设置表头
            setTitle(workbook, sheet, head);
            //设置单元格并赋值
            setData(sheet, data);
            //设置浏览器下载
            setBrowser(response, workbook, fileName);
            logger.info("导出成功!");
        } catch (Exception e) {
            logger.info("导出失败!");
            e.printStackTrace();
        }
    }

    /**
     * 方法名：setTitle
     * 功能：设置表头
     * 描述：
     * 创建人：typ
     * 创建时间：2018/10/19 10:20
     * 修改人：
     * 修改描述：
     * 修改时间：
     */
    private static void setTitle(HSSFWorkbook workbook, HSSFSheet sheet, String[] str) {
        try {
            HSSFRow row = sheet.createRow(0);
            //设置列宽，setColumnWidth的第二个参数要乘以256，这个参数的单位是1/256个字符宽度
            for (int i = 0; i <= str.length; i++) {
                sheet.setColumnWidth(i, 15 * 256);
            }
            //设置为居中加粗,格式化时间格式
            HSSFCellStyle style = workbook.createCellStyle();
            HSSFFont font = workbook.createFont();
            font.setBold(true);
            style.setFont(font);
            style.setDataFormat(HSSFDataFormat.getBuiltinFormat("m/d/yy h:mm"));
            //创建表头名称
            HSSFCell cell;
            for (int j = 0; j < str.length; j++) {
                cell = row.createCell(j);
                cell.setCellValue(str[j]);
                cell.setCellStyle(style);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 方法名：setData
     * 功能：表格赋值
     * 描述：
     * 创建人：typ
     * 创建时间：2018/10/19 16:11
     * 修改人：
     * 修改描述：
     * 修改时间：
     */
    private static void setData(HSSFSheet sheet, List<String[]> data) {
        try {
            int rowNum = 1;
            for (int i = 0; i < data.size(); i++) {
                HSSFRow row = sheet.createRow(rowNum);
                for (int j = 0; j < data.get(i).length; j++) {
                    row.createCell(j).setCellValue(data.get(i)[j]);
                }
                rowNum++;
            }
            logger.info("表格赋值成功！");
        } catch (Exception e) {
            logger.info("表格赋值失败！");
            e.printStackTrace();
        }
    }


    /**
     * 方法名：setBrowser
     * 功能：使用浏览器下载
     * 描述：
     * 创建人：typ
     * 创建时间：2018/10/19 16:20
     * 修改人：
     * 修改描述：
     * 修改时间：
     */
    public static void setBrowser(HttpServletResponse response, HSSFWorkbook workbook, String fileName) {
        try {
            //清空response
            response.reset();
            //设置response的Header
            response.addHeader("Content-Disposition", "attachment;filename=" + fileName);
            OutputStream os = new BufferedOutputStream(response.getOutputStream());
            response.setContentType("application/vnd.ms-excel;charset=gb2312");
            //将excel写入到输出流中
            workbook.write(os);
            os.flush();
            os.close();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }


    /**
     * 方法名：setBrowser
     * 功能：使用浏览器下载
     * 描述：
     * 创建人：typ
     * 创建时间：2018/10/19 16:20
     * 修改人：
     * 修改描述：
     * 修改时间：
     */
    public static void setBrowsers(HttpServletResponse response, Workbook workbook, String fileName){
        OutputStream os = null;
        try {
            //清空response
            response.reset();
            //设置response的Header
            response.addHeader("Content-Disposition", "attachment;filename=" + fileName);
            os = new BufferedOutputStream(response.getOutputStream());
            response.setContentType("application/vnd.ms-excel;charset=gb2312");
            //将excel写入到输出流中
            workbook.write(os);
            os.flush();
        } catch (Exception e) {
            e.printStackTrace();
        }
        finally {
            try{
                os.close();
            }
            catch(Exception e){
                e.printStackTrace();
            }
        }
    }


    public static void main(String[] args) {

    }
}
